####
#
# Copyright 2007 B. Chandler Carruth
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
####
#
# ./lib/rcons/files/cxx_application_target.rb
#
# This file provides the basic source file target functionality.
#
####

require( 'rcons/files/application_target' )
require( 'rcons/files/cxx_source_file_target' )
require( 'rcons/tools/cxx_compiler_target' )

module RCons

  # Provides C application functionality and manages all the associated
  # source files and compilers.
  class CxxApplicationTarget < ApplicationTarget

    # Initializes a C application target.  Determines which compiler to use
    # to compile the file based on registered compilers.
    #
    # Inputs:
    #
    # +build_env+:: an +Environment+.
    # +name+:: a name for the C application.
    # +opts+:: a list of options.
    def initialize( build_env, name, opts = Hash.new() )
      # early check for C compiler
      if opts[ :compiler ]
        @compiler = opts[ :compiler ]
      else
        @compiler = CxxCompilerTarget.best_klass().new( build_env )
      end

      raise( ArgumentError,
        "Unexpected type for compiler argument.",
        caller() ) unless @compiler.kind_of?( CxxCompilerTarget )

      # handle all the defaults for an application target
      super( build_env, name, opts )

      # setup our builder
      @builder.sources = []
      @builder.compiler = @compiler

      # add compiler and linker
      add_pre_dep( @compiler )

      # yield to a block
      yield( self )
    end

    # Adds source files to the application first creating a
    # +CxxSourceFileTarget+.  Primarily used to simpilify the
    # writing of build files.
    #
    # Inputs:
    #
    # +src_files+:: a list of paths to the source files associated with the application.
    def add_sources( *src_files )
      for src in src_files
        @builder.sources.push( CxxSourceFileTarget.new( @build_env, src, :compiler => @compiler ) )
        add_pre_dep( @builder.sources.last() )
      end
    end

    # The CxxApplicationTarget overriden Builder class.
    class Builder < superclass()::Builder
      attr_accessor( :sources, :compiler )

      # This is the custom method for building this type of target
      def do_build( has_changed )
        if has_changed or not File.exists?( @build_env.expand( @file_name ) )
          unless @compiler.link( @file_name,
                                 *( @sources.collect() { |s| s.file_name } ) )
            @build_env.print( "Failed to link '#{@build_env.expand( @file_name )}'" )
            return false
          end
          super( true )
        else
          super( false )
        end
      end
    end
  end
end

